package cc.rengu.igas.opms.core.service.trans.quickpay;

import cc.rengu.igas.bomp.facade.result.Result;
import cc.rengu.igas.channel.upac.facade.response.TokenPayOpenQueryResponse;
import cc.rengu.igas.opms.common.constant.OpmsParamConstant;
import cc.rengu.igas.opms.common.enums.RespCodeEnum;
import cc.rengu.igas.opms.common.enums.SignTokenTypeEnum;
import cc.rengu.igas.opms.common.enums.SignTypeEnum;
import cc.rengu.igas.opms.core.service.base.ManageService;
import cc.rengu.igas.opms.facade.base.BaseResponse;
import cc.rengu.igas.opms.facade.request.TokenSignStateQueryRequest;
import cc.rengu.igas.opms.facade.response.TokenSignStateQueryResponse;
import cc.rengu.igas.share.common.constant.ShareParamConstant;
import cc.rengu.igas.share.common.constant.TransCacheConstant;
import cc.rengu.igas.share.core.model.UserInfo;
import cc.rengu.igas.share.core.realize.UserService;
import cc.rengu.igas.share.core.realize.impl.UserServiceImpl;
import cc.rengu.oltp.service.base.ChannelBaseService;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.dao.NonFinanceTxnMapper;
import cc.rengu.oltp.service.common.dao.SignAcctInfoMapper;
import cc.rengu.oltp.service.common.dao.impl.NonFinanceTxnMapperImpl;
import cc.rengu.oltp.service.common.dao.impl.SignAcctInfoMapperImpl;
import cc.rengu.oltp.service.common.entity.*;
import cc.rengu.oltp.service.common.enums.CheckResultEnum;
import cc.rengu.oltp.service.common.enums.TransStatusEnum;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.service.model.OrderInfo;
import cc.rengu.oltp.service.realize.TransCustomImpl;
import cc.rengu.oltp.utility.util.*;
import com.alibaba.fastjson.JSON;

import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;


/**
 * 银联无跳转签约状态查询
 *
 * @author keyi
 * @modify by wangcheng
 * @date 2020/3/17.
 */
public class TokenSignStateQueryService extends ManageService implements TransCustomImpl {
    @Override
    protected Object bizBeforeCust() throws Exception {
        TokenSignStateQueryRequest tokenSignStateQueryRequest = new TokenSignStateQueryRequest();
        ConvertUtil.convertOutput(tokenSignStateQueryRequest);
        return tokenSignStateQueryRequest;
    }

    @Override
    protected BizResponse bizProcessCust(Object request) throws Exception {
        TokenSignStateQueryRequest tokenSignStateQueryRequest = (TokenSignStateQueryRequest) request;
        String instId = tokenSignStateQueryRequest.getHeader().getInstId();
        String acctNo = tokenSignStateQueryRequest.getSignAcctNo();

        //获取用户签约主体及签约类型信息
        UserService userService = new UserServiceImpl();
        String signInst = userService.getUserSignInst();
        String signType = null != platMchntInfo ? platMchntInfo.getSignType() : SignTypeEnum.BANK_CLASS_SIGN.getSignTypeCode();

        //根据账号获取所有签约记录
        SignAcctInfoMapper signAcctInfoMapper = new SignAcctInfoMapperImpl();
        List<SignAcctInfo> signAcctInfoList = signAcctInfoMapper.selectSignAcctInfoBySignAcctNo(instId, acctNo);
        if (null == signAcctInfoList || signAcctInfoList.isEmpty()) {
            rglog.info("全存渠道签约信息不在，确认用户是否做过全渠道签约");
            throw new BizException(RespCodeEnum.INVALID_SIGN.getRespCode(), RespCodeEnum.INVALID_SIGN.getRespDesc());
        }
        signAcctInfoList = signAcctInfoList.stream().filter(item -> item.getSignTokenType().equals(SignTokenTypeEnum.UPAC_TOKEN.getSignTypeCode()) &&
                item.getSignInst().equals(signInst) && item.getSignType().equals(signType) && item.getUserId().equals(tokenSignStateQueryRequest.getUserId())).collect(Collectors.toList());
        rglog.trace("获取到当前卡:<{}>在当前签约主体上:<{}>的签约记录:<{}>", acctNo, signInst, JSON.toJSONString(signAcctInfoList));
        SignAcctInfo signAcctInfo = signAcctInfoList.get(0);
        GlobalTransUtil.setCacheValue(TransCacheConstant.SIGN_ACCT_INFO, signAcctInfo);

        //查询非金融流水表获取原交易的业务类型，根据原签约交易的业务类型判断原交易的类型 签约:00/重新签约:01/修改签约手机号:02
        NonFinanceTxnMapper nonFinanceTxnMapper = new NonFinanceTxnMapperImpl();
        NonFinanceTxn nonFinanceTxn = nonFinanceTxnMapper.selectNonFinanceTxnInfoByPrimaryKey(instId, signAcctInfo.getSignSysSeqNum());
        if (null == nonFinanceTxn) {
            rglog.info("非金融交易流水表中不存在该笔交易");
            throw new BizException(RespCodeEnum.ORDER_NOEXIT.getRespCode(), RespCodeEnum.ORDER_NOEXIT.getRespDesc());
        }
        GlobalTransUtil.setCacheValue(TransCacheConstant.ORIG_NON_FINANCE_TXN, nonFinanceTxn);
        rglog.debug("原签约交易业务类型，bizType:<{}>", nonFinanceTxn.getBizType());

        //判断当前签约记录的签约状态是否已经更新完成-已经是Y的不再发起查询，修改签约手机号的交易允许发起查询
        if ("00".equals(nonFinanceTxn.getBizType()) || "01".equals(nonFinanceTxn.getBizType())) {
            if (!OpmsParamConstant.OPMS_PARAM_INIT.equals(signAcctInfo.getSignStatus())) {
                rglog.info("签约或重新签约的交易,签约关系表中该签约关系已经是终态:<{}>,不再向银联发起签约状态查询", signAcctInfo.getSignStatus());
                TokenSignStateQueryResponse tokenSignStateQueryResponse = new TokenSignStateQueryResponse();
                tokenSignStateQueryResponse.setHeader(tokenSignStateQueryRequest.getHeader());
                tokenSignStateQueryResponse.getHeader().setSession(tokenSignStateQueryRequest.getHeader().getSession());
                tokenSignStateQueryResponse.setUserId(signAcctInfo.getUserId());
                tokenSignStateQueryResponse.setSignStatus(signAcctInfo.getSignStatus());
                tokenSignStateQueryResponse.setSignBankNo(signAcctInfo.getSignBankNo());
                tokenSignStateQueryResponse.setSignBankName(signAcctInfo.getSignBankName());
                BizResponse<BaseResponse> bizResponse = new BizResponse<>();
                bizResponse.setResult(tokenSignStateQueryResponse);
                bizResponse.setRspSysId(AppParamConstant.SYS_ID);
                bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
                bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
                return bizResponse;
            }
        }

        //调用全渠道接口查询签约状态
        if (null == txnInfo.getChannelCallCfgList() || txnInfo.getChannelCallCfgList().isEmpty()) {
            rglog.error("<{}-{}>交易未配置交易通道服务调用配置信息！", txnInfo.getSrcTxnAuthCfg().getTxnNum(), txnInfo.getSrcTxnAuthCfg().getTxnName());
            throw new BizException(RespCodeEnum.CHANNEL_CONFIG_NOT_EXIST.getRespCode(), RespCodeEnum.CHANNEL_CONFIG_NOT_EXIST.getRespDesc());
        }
        List<ChannelCallCfg> channelCallCfgList = txnInfo.getChannelCallCfgList().stream().filter(item ->
                item.getCallIndex().equals(ChannelBaseService.FIRST_CHANNEL_CALL_INDEX)).collect(Collectors.toList());
        ChannelCallCfg channelCallCfg = channelCallSceneDiscern(tokenSignStateQueryRequest, channelCallCfgList);
        Class channelClasz = Class.forName(channelCallCfg.getCallChannelImpl());
        ChannelBaseService channelBaseService = (ChannelBaseService) channelClasz.newInstance();
        channelBaseService.callService(txnInfo, null, channelCallCfg.getBizScene(), request);

        //响应信息
        signAcctInfo = (SignAcctInfo) GlobalTransUtil.getCacheValue(TransCacheConstant.SIGN_ACCT_INFO);
        TokenSignStateQueryResponse tokenSignStateQueryResponse = new TokenSignStateQueryResponse();
        tokenSignStateQueryResponse.setHeader(tokenSignStateQueryRequest.getHeader());
        tokenSignStateQueryResponse.setUserId(tokenSignStateQueryRequest.getUserId());
        tokenSignStateQueryResponse.setSignStatus(Objects.requireNonNull(signAcctInfo).getSignStatus());
        tokenSignStateQueryResponse.setSignBankNo(signAcctInfo.getSignBankNo());
        tokenSignStateQueryResponse.setSignBankName(signAcctInfo.getSignBankName());
        BizResponse<BaseResponse> bizResponse = new BizResponse<>();
        bizResponse.setResult(tokenSignStateQueryResponse);
        bizResponse.setRspSysId(AppParamConstant.SYS_ID);
        bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
        return bizResponse;
    }

    @Override
    protected void bizAfterCust(Object response) throws Exception {
        BizResponse<TokenSignStateQueryResponse> bizResponse = (BizResponse<TokenSignStateQueryResponse>) response;
        TokenSignStateQueryResponse tokenSignStateQueryResponse = bizResponse.getResult();
        ConvertUtil.convertInput(tokenSignStateQueryResponse);
    }

    @Override
    public ChannelCallCfg channelCallSceneDiscern(Object request, List<ChannelCallCfg> channelCallCfgList) throws Exception {
        Optional<ChannelCallCfg> channelCallCfgOpt = channelCallCfgList.stream().filter(item ->
                item.getBizScene().equals(ShareParamConstant.CALL_CFG_DEFAULT_BIZ_SCENE)).findFirst();
        return channelCallCfgOpt.orElse(null);
    }

    @Override
    public CheckResultEnum channelCallPreCheck(Object request, ChannelCallCfg channelCallCfg, OrderInfo orderInfo) throws Exception {
        return CheckResultEnum.PASSED;
    }

    @Override
    public TransStatusEnum channelCallResultProc(Object request, ChannelCallCfg channelCallCfg, TransStatusEnum transStatusEnum, Object channelResponse, OrderInfo needUpdateOrderInfo) throws Exception {
        SignAcctInfo signAcctInfo = (SignAcctInfo) GlobalTransUtil.getCacheValue(TransCacheConstant.SIGN_ACCT_INFO);
        if (null != signAcctInfo && null != channelResponse) {
            Result<TokenPayOpenQueryResponse> callResult = (Result<TokenPayOpenQueryResponse>) channelResponse;
            TokenPayOpenQueryResponse tokenPayOpenQueryResponse = callResult.getResult();
            if (OpmsParamConstant.STR_ZERO.equals(tokenPayOpenQueryResponse.getActivateStatus())) {
                signAcctInfo.setSignStatus(AppParamConstant.NO);
            } else {
                updateSignAcctInfo(signAcctInfo, tokenPayOpenQueryResponse);
            }
            GlobalTransUtil.setCacheValue(TransCacheConstant.SIGN_ACCT_INFO, signAcctInfo);
        }
        return transStatusEnum;
    }

    /**
     * 更新签约信息
     *
     * @param signAcctInfo              签约信息
     * @param tokenPayOpenQueryResponse 全渠道签约查询结果
     * @throws Exception 异常
     */
    private void updateSignAcctInfo(SignAcctInfo signAcctInfo, TokenPayOpenQueryResponse tokenPayOpenQueryResponse) throws Exception {
        UserService userService = new UserServiceImpl();
        UserInfo userInfo = userService.getUserInfoByUserId(signAcctInfo.getInstId(), signAcctInfo.getUserId());
        if (userInfo == null) {
            rglog.error("用户不存在");
            throw new BizException(RespCodeEnum.USER_NOT_EXIT_ERROR.getRespCode(), RespCodeEnum.USER_NOT_EXIT_ERROR.getRespDesc());
        } else if (!"00".equals(userInfo.getUserStatus())) {
            rglog.error("用户已注销");
            throw new BizException(RespCodeEnum.USER_OUTLOG_ERROR.getRespCode(), RespCodeEnum.USER_OUTLOG_ERROR.getRespDesc());
        }
        NonFinanceTxn nonFinanceTxn = (NonFinanceTxn) GlobalTransUtil.getCacheValue(TransCacheConstant.ORIG_NON_FINANCE_TXN);
        if ("00".equals(Objects.requireNonNull(nonFinanceTxn).getBizType())) {
            rglog.info("原交易为签约交易,bizType:<{}>", nonFinanceTxn.getBizType());
            signAcctInfo.setSignToken(signAcctInfo.getSignBankNo() + "|" + tokenPayOpenQueryResponse.getTokenPayInfo().getToken());
            signAcctInfo.setSignExpiryDate(tokenPayOpenQueryResponse.getTokenPayInfo().getTokenEnd().substring(0, 8));
            signAcctInfo.setReserveMobileNo(tokenPayOpenQueryResponse.getCustomerInfo().getPhoneNo());
            if (!StringUtil.isEmptyOrNull(tokenPayOpenQueryResponse.getCustomerInfo().getCustName())) {
                signAcctInfo.setCardHoldName(tokenPayOpenQueryResponse.getCustomerInfo().getCustName());
            } else {
                signAcctInfo.setCardHoldName(userInfo.getUserName());
            }
            if (!StringUtil.isEmptyOrNull(tokenPayOpenQueryResponse.getCustomerInfo().getCertType())) {
                signAcctInfo.setCertType(tokenPayOpenQueryResponse.getCustomerInfo().getCertType());
            }
            if (!StringUtil.isEmptyOrNull(tokenPayOpenQueryResponse.getCustomerInfo().getCertNo())) {
                signAcctInfo.setCertNo(tokenPayOpenQueryResponse.getCustomerInfo().getCertNo());
            }
            signAcctInfo.setSignStatus(AppParamConstant.YES);
            signAcctInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
            if (StringUtil.isEmptyOrNull(userInfo.getMobileNo())) {
                userInfo.setMobileNo(tokenPayOpenQueryResponse.getCustomerInfo().getPhoneNo());
                userService.updateUserInfo(userInfo);
            }
        } else if ("01".equals(nonFinanceTxn.getBizType())) {
            rglog.info("原交易为重新签约交易，bizType:<{}>", nonFinanceTxn.getBizType());
            signAcctInfo.setSignToken(signAcctInfo.getSignBankNo() + "|" + tokenPayOpenQueryResponse.getTokenPayInfo().getToken());
            signAcctInfo.setSignExpiryDate(tokenPayOpenQueryResponse.getTokenPayInfo().getTokenEnd().substring(0, 8));
            signAcctInfo.setReserveMobileNo(tokenPayOpenQueryResponse.getCustomerInfo().getPhoneNo());
            if (!StringUtil.isEmptyOrNull(tokenPayOpenQueryResponse.getCustomerInfo().getCustName())) {
                signAcctInfo.setCardHoldName(tokenPayOpenQueryResponse.getCustomerInfo().getCustName());
            }
            if (!StringUtil.isEmptyOrNull(tokenPayOpenQueryResponse.getCustomerInfo().getCertType())) {
                signAcctInfo.setCertType(tokenPayOpenQueryResponse.getCustomerInfo().getCertType());
            }
            if (!StringUtil.isEmptyOrNull(tokenPayOpenQueryResponse.getCustomerInfo().getCertNo())) {
                signAcctInfo.setCertNo(tokenPayOpenQueryResponse.getCustomerInfo().getCertNo());
            }
            signAcctInfo.setSignStatus(AppParamConstant.YES);
            signAcctInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
        } else if ("02".equals(nonFinanceTxn.getBizType())) {
            rglog.info("原交易为修改银行预留手机号交易，bizType:<{}>，仅更新签约表的预留手机号", nonFinanceTxn.getBizType());
            signAcctInfo.setSignToken(signAcctInfo.getSignBankNo() + "|" + tokenPayOpenQueryResponse.getTokenPayInfo().getToken());
            signAcctInfo.setSignExpiryDate(tokenPayOpenQueryResponse.getTokenPayInfo().getTokenEnd().substring(0, 8));
            signAcctInfo.setReserveMobileNo(tokenPayOpenQueryResponse.getCustomerInfo().getPhoneNo());
            signAcctInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
        } else {
            rglog.error("不识别的原交易业务类型:<{}>", nonFinanceTxn.getBizType());
            throw new BizException(RespCodeEnum.NOT_SURP_TRANS_TYPE_ERROR.getRespCode(), RespCodeEnum.NOT_SURP_TRANS_TYPE_ERROR.getRespDesc());
        }
        SignAcctInfoMapper signAcctInfoMapper = new SignAcctInfoMapperImpl();
        if (signAcctInfoMapper.updateSignAcctInfoBySignAcctNo(signAcctInfo) != 0) {
            rglog.info("更新原签约信息失败");
            throw new BizException(RespCodeEnum.UPDATE_ORDER_ERROR.getRespCode(), RespCodeEnum.UPDATE_ORDER_ERROR.getRespDesc());
        }
    }
}
